package com.saihai.web.controller.system;

import com.alibaba.fastjson2.JSONObject;
import com.saihai.common.constant.Constants;
import com.saihai.common.core.domain.AjaxResult;
import com.saihai.common.core.domain.entity.SysMenu;
import com.saihai.common.core.domain.entity.SysUser;
import com.saihai.common.core.domain.model.LoginBody;
import com.saihai.common.core.domain.model.LoginUser;
import com.saihai.common.utils.ServletUtils;
import com.saihai.common.utils.StringUtils;
import com.saihai.common.utils.http.HttpUtils;
import com.saihai.framework.web.service.SysLoginService;
import com.saihai.framework.web.service.SysPermissionService;
import com.saihai.framework.web.service.TokenService;
import com.saihai.jiankang.jkUser.domain.JkUser;
import com.saihai.jiankang.jkUser.service.IJkUserService;
import com.saihai.system.service.ISysMenuService;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.*;

/**
 * 登录验证
 * 
 * @author ruoyi
 */
@RestController
public class SysLoginController
{
    @Value("${wx.APP_ID}")
    private String appId;

    @Value("${wx.APP_KEY}")
    private String secret;

    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IJkUserService jkUserService;

    /**
     * 登录方法
     * 
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 医生端小程序登陆
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/ys/login")
    public AjaxResult ysLogin(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        Map<String,Object> map = loginService.ysLogin(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, map.get("token"));
        ajax.put("info",map);
        return ajax;
    }

    /**
     * 医生端小程序 切换角色
     *
     */
    @GetMapping("/ys/switchRole/{id}")
    public AjaxResult switchRole(@PathVariable("id") Long id)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        Map<String,Object> map = loginService.switchRole(id);
        ajax.put("info",map);
        return ajax;
    }



    /**
     * 医生端小程序登陆
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/ys/ysLoginPhone")
    public AjaxResult ysLoginPhone(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
            // 生成令牌
            Map<String,Object> map = loginService.ysLoginPhone(loginBody.getUsername(),loginBody.getCode());
            ajax.put(Constants.TOKEN, map.get("token"));
            ajax.put("info",map);

        return ajax;
    }


    /**
     * 家长端小程序登录
     *
     * @param code 小程序code返回的临时凭证
     * @return
     */
    @GetMapping(value = "/ys/getAccessToken")
    public AjaxResult getOpenId(String code)
    {
        String wx = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/token", "grant_type=" + "client_credential" + "&appid=" + appId + "&secret=" + secret);
        JSONObject jsonObject = JSONObject.parseObject(wx);
        String access_token = jsonObject.get("access_token").toString();
        Map<String,String> map = new HashMap<>();
        map.put("access_token",access_token);
        return AjaxResult.success(map);
    }



    /**
     * 家长端小程序登录
     *
     * @param code 小程序code返回的临时凭证
     * @return
     */
    @GetMapping(value = "/jk/login")
    public AjaxResult login(String code)
    {
        String wx = HttpUtils.sendGet("https://api.weixin.qq.com/sns/jscode2session", "appid=" + appId + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code");
        JSONObject jsonObject = JSONObject.parseObject(wx);
        String sessionKey = jsonObject.get("session_key").toString();
        String openid = jsonObject.get("openid").toString();
        try
        {

            if (StringUtils.isEmpty(openid))
            {
                return AjaxResult.error("登录失败，无效的登录凭证");
            }
            JSONObject res = new JSONObject();

            JkUser JkUser = new JkUser();
            JkUser.setOpenid(openid);
            List<JkUser> JkUsers = jkUserService.selectJkUserList(JkUser);

            // 生成令牌
            String token = loginService.wxLogin(openid, sessionKey);
            res.put(Constants.TOKEN, token);
            res.put("rows",JkUsers);
            res.put("openid",openid);
            res.put("sessionKey",sessionKey);
            AjaxResult ajax = AjaxResult.success();
            ajax.put("data",res);
            return ajax;
        }
        catch (Exception e)
        {
            String msg = "接口异常";
            if (StringUtils.isNotEmpty(e.getMessage()))
            {
                msg = e.getMessage();
            }
            return AjaxResult.error(msg);
        }
    }

    //微信授权手机号登录
    @GetMapping(value = "/ys/wxPhoneLogin")
    public AjaxResult wxPhoneLogin(String phoneNumber) {
        if (StringUtils.isBlank(phoneNumber)) {
            return AjaxResult.error("获取手机号失败！");
        }
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        Map<String,Object> map = loginService.ysLoginPhone(phoneNumber,"9999");
        ajax.put(Constants.TOKEN, map.get("token"));
        ajax.put("info",map);

        return ajax;
    }

    public String getPhoneNumber(String encryptedData,String iv,String sessionKey, String openId) {
        String phoneNumber = "";
        byte[] dataByte = new byte[0];
        byte[] keyByte = new byte[0];
        byte[] ivByte = new byte[0];
        try {
            //这个替换字符特别重要，不写就报错。
            String replace = URLEncoder.encode(encryptedData, "UTF-8").replace("%3D", "=").replace("%2F", "/").replace("%2B", "+");
            //我这里不知道为什么必须这样使用base64其他小伙伴如果报错的话把前面的包名去掉试试
            dataByte = org.apache.commons.codec.binary.Base64.decodeBase64(replace);
            String replace2 = URLEncoder.encode(sessionKey, "UTF-8").replace("%3D", "=").replace("%2F", "/").replace("%2B", "+");
            keyByte = org.apache.commons.codec.binary.Base64.decodeBase64(replace2);
            String replace1 = URLEncoder.encode(iv, "UTF-8").replace("%3D", "=").replace("%2F", "/").replace("%2B", "+");
            ivByte = org.apache.commons.codec.binary.Base64.decodeBase64(replace1);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try {
            // 如果密钥不足16位，那么就补足. 这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            // 初始化
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String s = new String(resultByte, "UTF-8");
                JSONObject jsonObject = JSONObject.parseObject(s);
                phoneNumber = jsonObject.getString("phoneNumber");
                return phoneNumber;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return phoneNumber;
    }

    @GetMapping(value = "/jk/getPhone")
    public AjaxResult getPhone(String encryptedData,String iv,String sessionKey, String openId) {
        String phoneNumber = "";
        byte[] dataByte = new byte[0];
        byte[] keyByte = new byte[0];
        byte[] ivByte = new byte[0];
        try {
            //这个替换字符特别重要，不写就报错。
            String replace = URLEncoder.encode(encryptedData, "UTF-8").replace("%3D", "=").replace("%2F", "/").replace("%2B", "+");
            //我这里不知道为什么必须这样使用base64其他小伙伴如果报错的话把前面的包名去掉试试
            dataByte = org.apache.commons.codec.binary.Base64.decodeBase64(replace);
            String replace2 = URLEncoder.encode(sessionKey, "UTF-8").replace("%3D", "=").replace("%2F", "/").replace("%2B", "+");
            keyByte = org.apache.commons.codec.binary.Base64.decodeBase64(replace2);
            String replace1 = URLEncoder.encode(iv, "UTF-8").replace("%3D", "=").replace("%2F", "/").replace("%2B", "+");
            ivByte = org.apache.commons.codec.binary.Base64.decodeBase64(replace1);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try {
            // 如果密钥不足16位，那么就补足. 这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            // 初始化
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String s = new String(resultByte, "UTF-8");
                JSONObject jsonObject = JSONObject.parseObject(s);
                phoneNumber = jsonObject.getString("phoneNumber");
                JkUser jkUser = new JkUser();
                jkUser.setOpenid(openId);
                List<JkUser> list = jkUserService.selectJkUserList(jkUser);
                if (list.size() == 1) {
                    jkUser.setId(list.get(0).getId());
                    jkUser.setMobile(phoneNumber);
                    int i = jkUserService.updateJkUser(jkUser);
                    if (i == 1) {
                        Map<String, String> map = new HashMap<>(1);
                        map.put("phoneNumber", phoneNumber);
                        return AjaxResult.success(map);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.error();
    }

    /**
     * 获取用户信息
     * 
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        SysUser user = loginUser.getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }

    /**
     * 获取路由信息
     * 
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        // 用户信息
        SysUser user = loginUser.getUser();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(user.getUserId());
        return AjaxResult.success(menuService.buildMenus(menus));
    }
}
